package com.bolingcavalry.crm.security.config;

import com.bolingcavalry.crm.user.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * JWT Token 过滤器，用于验证请求中的 JWT 令牌并设置 Spring Security 上下文中的认证信息。
 *
 * <p>该过滤器会在每个请求到达控制器之前执行，检查请求头中的 Authorization 字段，
 * 提取 JWT 令牌并验证其有效性。如果令牌有效，则解析其中的用户名和角色信息，
 * 创建 {@link UsernamePasswordAuthenticationToken} 对象并将其设置到 Spring Security 上下文中。</p>
 */
@Component
public class JwtTokenFilter extends OncePerRequestFilter {

    /**
     * JWT 工具类，用于生成和验证 JWT 令牌。
     */
    private final JwtUtil jwtUtil;

    /**
     * 构造函数，通过依赖注入初始化 JWT 工具类。
     *
     * @param jwtUtil JWT 工具类实例
     */
    @Autowired
    public JwtTokenFilter(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    /**
     * 过滤器的核心方法，用于处理每个请求。
     *
     * <p>该方法会从请求头中提取 JWT 令牌，验证其有效性，并根据令牌中的信息设置 Spring Security 上下文中的认证信息。</p>
     *
     * @param request     当前 HTTP 请求
     * @param response    当前 HTTP 响应
     * @param filterChain 过滤器链
     * @throws ServletException 如果发生 Servlet 异常
     * @throws IOException      如果发生 IO 异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {
        // 从请求头中获取 Authorization 字段
        String token = request.getHeader("Authorization");

        // 检查 Authorization 字段是否存在且以 "Bearer " 开头
        if (token != null && token.startsWith("Bearer ")) {
            // 去掉 "Bearer " 前缀，获取纯 JWT 令牌
            token = token.replace("Bearer ", "");

            // 验证 JWT 令牌的有效性
            if (jwtUtil.validateToken(token)) {
                // 解析 JWT 令牌获取用户名
                String username = jwtUtil.getUsernameFromToken(token);

                // 解析 JWT 令牌获取角色
                List<String> role = jwtUtil.getRoleFromToken(token);

                // 正确方式：将每个角色单独加上 ROLE_ 前缀
                List<String> rolesWithPrefix = role.stream()
                        .map(r -> "ROLE_" + r)
                        .collect(Collectors.toList());
                // 创建权限列表，格式为 "ROLE_<role>"
                var authorities = AuthorityUtils.createAuthorityList(rolesWithPrefix.toArray(new String[0]));

                // 创建 UsernamePasswordAuthenticationToken 对象
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(username, null, authorities);

                // 设置认证详细信息（请求的详细信息）
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                // 将认证信息设置到 Spring Security 上下文中
                SecurityContextHolder.getContext().setAuthentication(authentication);
                System.out.println("Authorities: " + authentication.getAuthorities());

            }
        }

        // 继续过滤器链
        filterChain.doFilter(request, response);
    }
}
